package com.ikingtech.platform.service.push.dingtalk.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.push.dingtalk.config.DingTalkConfig;
import com.ikingtech.platform.service.push.dingtalk.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

/**
 * created on 2023-05-24 18:19
 * 钉钉自定义机器人消息
 *
 * @author wub
 */

@Slf4j
@Service
public class DingTalkService {


    public DeliverResult sendMessage(DingTalkSendMessageDTO dto) {
        DingTalkRobotMessageDTO message = new DingTalkRobotMessageDTO();
        message.setMsgtype(DingTalkConfig.ACTION_CARD.getValue());
        //消息标题和消息内容
        DingTalkRobotActionCardMessageDTO content = new DingTalkRobotActionCardMessageDTO();
        content.setText("<font face=\"黑体\" color=\"#4B9FD5\">**" + dto.getTitle() + "**</font>" + "\n\n" + dto.getContent());
        //默认卡片按钮横向
        if (Tools.Str.isBlank(dto.getBtnOrientation())) {
            content.setBtnOrientation(DingTalkConfig.BTN_ACROSS.getValue());
        }
        //消息按钮链接
        if (Tools.Coll.isNotBlank(dto.getButtonDTOList())) {
            List<DingTalkRobotActionCardMessageDTO.Button> btnS = new ArrayList<>(dto.getButtonDTOList().size());
            for (ButtonDTO e : dto.getButtonDTOList()) {
                DingTalkRobotActionCardMessageDTO.Button btn = new DingTalkRobotActionCardMessageDTO.Button();
                btn.setTitle(e.getTitle());
                btn.setActionURL("dingtalk://dingtalkclient/page/link?url=" + URLEncoder.encode(e.getUrl(), StandardCharsets.UTF_8) + "&pc_slide=false");
                btnS.add(btn);
            }
            content.setBtns(btnS);
        }
        message.setActionCard(content);

        //钉钉的安全设置,一种是加签的一种是非加签的
        String urlString;
        if (Tools.Str.isBlank(dto.getSecret())) {
            urlString = dto.getWebhook();
        } else {
            Long timestamp = System.currentTimeMillis();
            urlString = String.format("%s&timestamp=%s&sign=%s", dto.getWebhook(), timestamp, this.getSign(dto.getSecret(), timestamp));
        }
        //发送消息
        String result;
        try {
            result = Tools.Http.post(urlString, Tools.Json.toJsonStr(message));
        } catch (Exception e) {
            throw new FrameworkException("push-dingTalk", e.getMessage());
        }
        DingTalkResponse dingTalkResponse = Tools.Json.toBean(result, new TypeReference<>() {
        });
        if (dingTalkResponse != null) {
            if (dingTalkResponse.success()) {
                //发送成功
                //记录...
                return new DeliverResult(true, Tools.Str.EMPTY);
            } else {
                //发送失败
                //记录...
                return new DeliverResult(false, dingTalkResponse.getErrmsg());
            }
        } else {
            throw new FrameworkException("push-dingTalk", "dingTalk消息发送失败 result=" + result);
        }
    }


    /**
     * 自定义机器人安全设置(加签方式)
     * 把 timestamp+"\n"+ 密钥当做签名字符串，使用HmacSHA256算法计算签名，然后进行Base64 encode，最后再把签名参数再进行urlEncode，得到最终的签名（需要使用UTF-8字符集）
     *
     * @param timestamp 当前时间戳
     * @return 加密后的签名
     */
    private String getSign(String secret, Long timestamp) {

        String stringToSign = timestamp + "\n" + secret;
        String encode;
        try {
            Mac mac = Mac.getInstance(DingTalkConfig.HMAC_ALGORITHM.getValue());
            mac.init(new SecretKeySpec(secret.getBytes(String.valueOf(StandardCharsets.UTF_8)), DingTalkConfig.HMAC_ALGORITHM.getValue()));
            byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
            encode = URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), String.valueOf(StandardCharsets.UTF_8));
        } catch (Exception e) {
            encode = Tools.Str.EMPTY;
        }
        return encode;
    }

}
